﻿#include "updater.h"

Updater::Updater(QWidget *parent)
    : QWidget(parent)
{
    createStorage();
    startDownloader();
    checkSpace();
}

Updater::~Updater()
{
    downloadThread.quit();
    downloadThread.wait();
}

void Updater::checkSpace()
{
    QDir dir(FHS_UPDATE);
    QStringList fileList=dir.entryList(QDir::Files);

    foreach (QString entry, fileList) {
        QFile file(entry);
        if(file.open(QFile::ReadOnly))
        {
            QJsonDocument doc=QJsonDocument::fromBinaryData(file.readAll());
            if(!doc.isObject())
                break;

            checkEntry(doc.object());
        }
    }

    qInfo() << QStringLiteral("更新目标：") + QString::number(updateFiles.size())
               + QStringLiteral("；下载：") + QString::number(downloadFiles.size());

    if(!downloadFiles.isEmpty())
    {
        emit downloadUrls(downloadFiles);
    }
    else
    {
        if(!updateFiles.isEmpty())
            operate_move();
        else
            qApp->quit();
    }
}

void Updater::downloadFinished(const QString &url)
{
    downloadFiles.removeOne(url);

    QSqlQuery query;
    query.exec(QString("select * from main where url='%1'").arg(url));
    if(query.next())
    {
        QString uid=query.value("uid").toString();
        QString fileName=query.value("fileName").toString();
        QString sha1=query.value("sha1").toString();

        QString filePath=P_FHS_TMP + fileName;
        if(operate_verify(filePath,sha1))
            QFile::remove(P_FHS_UPDATE + uid);
    }

    if(downloadFiles.isEmpty())
        operate_move();
}

bool Updater::operate_verify(const QString &filePath, const QString &sha1)
{
    if(!QFile::exists(filePath))
        return false;
    else
    {
        QString _sha1=sp_verifyFile(QCryptographicHash::Sha1,filePath);
        return _sha1==sha1;
    }
}

void Updater::operate_move()
{
    foreach (QString source, updateFiles) {
        QFileInfo fi(source);
        QString destination=qApp->applicationDirPath() + "/" + fi.fileName();
        QFile file(source);
        if(file.copy(destination))
            file.remove();
    }
    qApp->quit();
}

void Updater::checkEntry(const QJsonObject &obj)
{
    QString uid=obj.value("uid").toString();
    QString name=obj.value("name").toString();
    QString fileName=obj.value("fileName").toString();
    QString sha1=obj.value("sha1").toString();
    QString url=obj.value("url").toString();

    QString filePath=P_FHS_TMP + fileName;
    updateFiles.append(filePath);
    if(operate_verify(filePath,sha1))
        return;

    QSqlQuery query;
    query.prepare("insert into main values (?,?,?,?,?)");
    query.addBindValue(uid);
    query.addBindValue(name);
    query.addBindValue(fileName);
    query.addBindValue(sha1);
    query.addBindValue(url);
    if(!query.exec())
        qDebug() << "INSERT ERROR : " + query.lastError().text();
    else
        downloadFiles.append(url);
}

void Updater::createStorage()
{
    db=::sp_createLocalStorage(":memory:");
    if(db_try())
    {
        QSqlQuery query;
        QString sql="CREATE TABLE main (uid TEXT,name TEXT,fileName TEXT,sha1 TEXT,url TEXT)";
        if(!query.exec(sql))
            qDebug() << "CREATE ERROR : " + query.lastError().text();
    }
    else
        qCritical() << "can not open db";
}

bool Updater::db_try()
{
    if(!db.isOpen())
        return db.open();
    else
        return true;
}

void Updater::startDownloader()
{
    downloader=new Downloader;
    downloader->setDestination(FHS_TMP);
    connect(this,&Updater::downloadUrls,downloader,&Downloader::downloadUrls);
    connect(downloader,&Downloader::downloadFinished,this,&Updater::downloadFinished);
    connect(&downloadThread,&QThread::finished,downloader,&Downloader::deleteLater);
    downloader->moveToThread(&downloadThread);
    downloadThread.start();
}
